﻿using System;
using System.Threading.Tasks;
using Devonline.Core;
using Devonline.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;

namespace Devonline.MessageCenter
{
    public class SignalHub<TClient, T> : Hub<TClient> where TClient : class, IChannelClient<T>
    {
        protected private readonly ILogger<SignalHub<TClient, T>> _logger;
        protected private readonly IDistributedCache _cache;
        protected private readonly HttpContext _httpContext;
        protected private readonly McSetting _appSetting;

        public SignalHub(
            ILogger<SignalHub<TClient, T>> logger,
            IDistributedCache cache,
            IHttpContextAccessor httpContextAccessor,
            McSetting setting
            )
        {
            _httpContext = httpContextAccessor.HttpContext;
            _logger = logger;
            _cache = cache;
            _appSetting = setting;
        }

        /// <summary>
        /// 客户端连接到服务器时
        /// </summary>
        /// <returns></returns>
        public override async Task OnConnectedAsync()
        {
            var userId = GetUserId();
            if (userId.IsNullOrEmpty())
            {
                _logger.LogError("There has no user identity in client connection");
                return;
            }

            //记录当前客户端和客户端连接的对应关系
            _logger.LogWarning("Client user {userId} connected with connectionId: {connectionId}", userId, Context.ConnectionId);
            await Groups.AddToGroupAsync(Context.ConnectionId, userId);
            await base.OnConnectedAsync();
        }

        /// <summary>
        /// 客户端从服务器断开时
        /// </summary>
        /// <param name="exception"></param>
        /// <returns></returns>
        public override async Task OnDisconnectedAsync(Exception exception)
        {
            var userId = GetUserId();
            if (userId.IsNullOrEmpty())
            {
                _logger.LogError("There has no user identity in client connection");
                return;
            }

            //移除当前用户和客户端连接的对应关系
            _logger.LogWarning("Client user {userId} disconnected with connectionId: {connectionId}", userId, Context.ConnectionId);
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, userId);
            await base.OnDisconnectedAsync(exception);
        }

        /// <summary>
        /// 获取当前连接的客户端用户标识
        /// </summary>
        /// <returns></returns>
        protected virtual string GetUserId() => _httpContext.GetContextOption<string>(_appSetting.ClientId) ?? _httpContext.GetUserId();
    }
}
